package com.doudou.pay.helper.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradeOrderSettleRequest;
import com.alipay.api.response.AlipayTradeOrderSettleResponse;
import com.doudou.pay.helper.commons.IdWorker;
import com.doudou.pay.helper.commons.JsonResult;
import com.doudou.pay.helper.commons.PayConstans;
import com.doudou.pay.helper.commons.PayRedisKey;
import com.doudou.pay.helper.entities.Accounts;
import com.doudou.pay.helper.entities.Config;
import com.doudou.pay.helper.entities.CustomRate;
import com.doudou.pay.helper.entities.IntraAccounts;
import com.doudou.pay.helper.entities.MerchantDeductionDetail;
import com.doudou.pay.helper.entities.MerchantOrderQuery;
import com.doudou.pay.helper.entities.MerchantRate;
import com.doudou.pay.helper.entities.MerchantRechargeRecord;
import com.doudou.pay.helper.entities.Package;
import com.doudou.pay.helper.entities.PayAccounts;
import com.doudou.pay.helper.entities.PayOrder;
import com.doudou.pay.helper.entities.PayUser;
import com.doudou.pay.helper.entities.RechargeAccounts;
import com.doudou.pay.helper.entities.ResponsePay;
import com.doudou.pay.helper.entities.Seller;
import com.doudou.pay.helper.entities.User;
import com.doudou.pay.helper.entities.UserPay;
import com.doudou.pay.helper.mapper.AccountsMapper;
import com.doudou.pay.helper.mapper.ConfigMapper;
import com.doudou.pay.helper.mapper.CustomRateMapper;
import com.doudou.pay.helper.mapper.IntraAccountsMapper;
import com.doudou.pay.helper.mapper.MerchantDeductionDetailMapper;
import com.doudou.pay.helper.mapper.MerchantRateMapper;
import com.doudou.pay.helper.mapper.MerchantRechargeRecordMapper;
import com.doudou.pay.helper.mapper.PackageMapper;
import com.doudou.pay.helper.mapper.PayOrderMapper;
import com.doudou.pay.helper.mapper.RechargeAccountsMapper;
import com.doudou.pay.helper.mapper.TransferMapper;
import com.doudou.pay.helper.mapper.UserMapper;
import com.doudou.pay.helper.server.handler.WriteMsgHandler;
import com.doudou.pay.helper.server.protoco.ProtocoConsts;
import com.doudou.pay.helper.service.AuthTokenStrategyService;
import com.doudou.pay.helper.service.MessageCacheService;
import com.doudou.pay.helper.service.PayService;
import com.doudou.pay.helper.service.PayUserService;
import com.doudou.pay.helper.websocket.PayWebsocketHandler;
import com.doudou.pay.helper.websocket.WebSocketResponse;

@Service("payService")
public class PayServiceImpl implements PayService {

	@Autowired
	private IdWorker idWorker;

	@Autowired
	private PayWebsocketHandler payWebsocketHandler;

	@Autowired
	private PayOrderMapper payOrderMapper;

	@Autowired
	private MessageCacheService messageCacheService;

	@Autowired
	private AuthTokenStrategyService authTokenStrategyService;

	@Autowired
	private StringRedisTemplate stringRedisTemplate;

	@Autowired
	private PayUserService payUserService;

	@Autowired
	private RestTemplate restTemplate;
	//
	// @Autowired
	// private MerchantUserMapper merchantUserMapper;

	@Autowired
	private MerchantRateMapper merchantRateMapper;

	@Autowired
	private MerchantDeductionDetailMapper merchantDeductionDetailMapper;

	@Autowired
	private MerchantRechargeRecordMapper merchantRechargeRecordMapper;

	@Autowired
	private UserMapper userMapper;

	@Autowired
	private AccountsMapper accountsMapper;

	@Autowired
	private CustomRateMapper customRateMapper;

	@Autowired
	private PackageMapper packageMapper;

	@Autowired
	private RechargeAccountsMapper rechargeAccountsMapper;

	@Autowired
	private IntraAccountsMapper intraAccountsMapper;

	@Autowired
	private ConfigMapper configMapper;

	@Autowired
	private TransferMapper transferMapper;

	@Override
	public WebSocketResponse pay(UserPay userPay, Map<String, Integer> clientMap) {

		userPay.setPayId(idWorker.nextId() + "");
		userPay.setTime(System.currentTimeMillis());
		userPay.setAuthToken(authTokenStrategyService
				.selectAuthToken(clientMap));
		System.out.println("服务端发起支付:" + JSON.toJSONString(userPay));

		// 更新对应authToken的使用计数
		String redisKey = PayRedisKey.getUserTokenHashKey(userPay.getUserId());
		stringRedisTemplate.opsForHash().increment(redisKey,
				userPay.getAuthToken(), 1);

		WebSocketResponse response = new WebSocketResponse();
		response.setMsgType(ProtocoConsts.TCP_MSG_TYPE_REQUEST_PAY);
		response.setCode(ProtocoConsts.FAIL);

		if (WriteMsgHandler.writePay(userPay)) {
			response.setCode(ProtocoConsts.SUCCESS);
			response.setData(userPay);

			PayOrder payorder = new PayOrder(userPay);
			payorder.setStatus(PayConstans.PAY_STATUS_REQUEST);
			payorder.setUserId(userPay.getUserId());
			payOrderMapper.insert(payorder);
		} else {
			// 更新对应authToken的使用计数
			stringRedisTemplate.opsForHash().increment(redisKey,
					userPay.getAuthToken(), -1);
		}
		return response;
	}

	@Override
	public WebSocketResponse pay(UserPay userPay, User user) {

		userPay.setTime(System.currentTimeMillis());
		System.out.println("服务端发起支付:" + JSON.toJSONString(userPay));

		WebSocketResponse response = new WebSocketResponse();
		response.setMsgType(ProtocoConsts.TCP_MSG_TYPE_REQUEST_PAY);
		response.setCode(ProtocoConsts.FAIL);

		if (user.getPackageId() != 3) {
			CustomRate customRate = customRateMapper.findByUserId(user
					.getUsername());
			Double payRate = 0.0;
			if (customRate != null) {
				payRate = customRate.getRate();
			} else {
				Package packageEntity = packageMapper.findPackageById(user
						.getPackageId());
				payRate = packageEntity.getRate();
			}

			double deductionMoney = this.calRate(payRate, userPay.getMoney());
			if (deductionMoney > user.getBalance()) {
				return response;
			}
		} else {
			if (user.getExpireDate().getTime() < (new Date()).getTime()) {
				return response;
			}
		}

		response.setCode(ProtocoConsts.SUCCESS);
		response.setData(userPay);

		PayOrder payorder = new PayOrder(userPay);
		payorder.setPayId(userPay.getPayId());
		payorder.setThirdPartyOrderId(userPay.getRemark());
		payorder.setStatus(PayConstans.PAY_STATUS_REQUEST);
		payorder.setUserId(userPay.getUserId());
		payorder.setType(userPay.getType());
		payorder.setMoney(userPay.getMoney());
		payorder.setRemark(userPay.getRemark());
		payorder.setPayTime(new Date());
		payorder.setFundsAccount(userPay.getFundsAccount());
		payorder.setPayType(userPay.getPayType());
		payorder.setRechargeAccount("");
		payorder.setFundsAccountName(userPay.getFundsAccountName());
		payorder.setClientType(userPay.getClientType());
		payorder.setQrcode(userPay.getQrcode());
		payOrderMapper.insert(payorder);

		return response;
	}

	@Override
	public boolean responsePay(int code, ResponsePay responsePay) {

		JsonResult jsonResult = new JsonResult();
		jsonResult.setCode(ProtocoConsts.SUCCESS);

		PayUser payUser = payUserService.getPayUserByAuthToken(responsePay
				.getAuthToken());
		String redisKey = PayRedisKey.getUserTokenHashKey(payUser.getUserId());
		stringRedisTemplate.opsForHash().increment(redisKey,
				payUser.getAuthToken(), -1);

		WebSocketResponse response = new WebSocketResponse();
		if (code == ProtocoConsts.SUCCESS) {
			// 更新对应authToken的使用计数
			jsonResult.setCode(ProtocoConsts.SUCCESS);

			response.setMsgType(ProtocoConsts.TCP_MSG_TYPE_RESPONSE_PAY);
			response.setCode(ProtocoConsts.SUCCESS);
			response.setData(responsePay);

			jsonResult.setResult(response);

			this.updatePayStatus(PayConstans.PAY_STATUS_RESPONSE,
					responsePay.getPayId());
		} else {
			response.setCode(ProtocoConsts.FAIL);
			jsonResult.setDefine("支付失败");

			this.updatePayStatus(PayConstans.PAY_STATUS_QRCODE_FAIL,
					responsePay.getPayId());
		}
		payWebsocketHandler.sendTextMsg(responsePay.getSessionKey(),
				JSON.toJSONString(jsonResult));
		return true;
	}

	@Override
	public boolean responseHttpPay(ResponsePay responsePay) {

		PayUser payUser = payUserService.getPayUserByAuthToken(responsePay
				.getAuthToken());
		String redisKey = PayRedisKey.getUserTokenHashKey(payUser.getUserId());
		stringRedisTemplate.opsForHash().increment(redisKey,
				payUser.getAuthToken(), -1);

		messageCacheService.setResponsePay(responsePay);

		if (responsePay.getCode() == ProtocoConsts.SUCCESS) {
			this.updatePayStatus(PayConstans.PAY_STATUS_RESPONSE,
					responsePay.getPayId());
		} else {
			this.updatePayStatus(PayConstans.PAY_STATUS_QRCODE_FAIL,
					responsePay.getPayId());
		}
		return false;
	}

	@Override
	public int updatePayStatus(String status, String payId) {
		PayOrder payOrder = new PayOrder();
		payOrder.setStatus(status);
		payOrder.setPayId(payId);
		return this.payOrderMapper.update(payOrder);
	}

	@Override
	public boolean isExisPayOrder(String authToken, String payId) {
		PayOrder payOrder = new PayOrder();
		payOrder.setAuthToken(authToken);
		payOrder.setPayId(payId);

		List<PayOrder> payOrders = this.payOrderMapper.select(payOrder);
		if (null != payOrders && payOrders.size() > 0) {
			return true;
		}
		return false;
	}

	@Transactional(rollbackFor = Throwable.class)
	@Override
	public int updatePayInfo(String status, User user, String payId,
			String platformOrder, String platformOrderStatus) {

		PayOrder payOrder = this.payOrderMapper.selectById(payId);
		// if(payOrder==null){
		// payOrder =
		// this.payOrderMapper.selectOrderByUserIdAndThirdPartyOrderId("admin",
		// thirdPartyOrderId);
		// }

		if (payOrder == null) {
			return 0;
		}

		if (!"1".equals(payOrder.getStatus())) {
			return 0;
		}

		if (payOrder.getPayType() == 1) {
			userMapper.updateBalance(payOrder.getRechargeAccount(),
					payOrder.getMoney());

			MerchantRechargeRecord merchantRechargeRecord = new MerchantRechargeRecord();
			merchantRechargeRecord.setPayType(payOrder.getType());
			merchantRechargeRecord.setPlatformOrder(platformOrder);
			merchantRechargeRecord.setRechargeMoney(payOrder.getMoney());
			merchantRechargeRecord.setRechargeTime(new Date());
			merchantRechargeRecord.setUserId(payOrder.getUserId());
			merchantRechargeRecord.setClientType(payOrder.getClientType());
			merchantRechargeRecordMapper.insert(merchantRechargeRecord);

			Map<String, Object> map = new HashMap<String, Object>();
			map.put("accountName", payOrder.getFundsAccount());
			map.put("money", payOrder.getMoney());
			rechargeAccountsMapper.updatePayMoney(map);

		} else {
			// 对商户余额扣款与添加扣款明细
			if (PayConstans.PAY_STATUS_SUCCESS.equals(status)) {
				if (user.getPackageId() != 3) {
					// 费率
					CustomRate customRate = customRateMapper.findByUserId(user
							.getUsername());
					Double payRate = 0.0;
					if (customRate != null) {
						payRate = customRate.getRate();
					} else {
						Package packageEntity = packageMapper
								.findPackageById(user.getPackageId());
						payRate = packageEntity.getRate();
					}

					double deductionMoney = this.calRate(payRate,
							payOrder.getMoney());
					MerchantDeductionDetail merchantDeductionDetail = new MerchantDeductionDetail(
							payOrder, deductionMoney);
					merchantDeductionDetail.setRate(user.getPayRate());
					merchantDeductionDetailMapper
							.insert(merchantDeductionDetail);
					userMapper.updateBalance(user.getUsername(),
							-deductionMoney);
				}

				if (user.getPackageId() == 2) {
					userMapper.updateAmount(user.getUsername(),
							payOrder.getMoney());
				}

				if (user.getPackageId() != 2) {
					Map<String, Object> map = new HashMap<String, Object>();
					map.put("userId", payOrder.getUserId());
					map.put("accountName", payOrder.getFundsAccount());
					map.put("money", payOrder.getMoney());
					accountsMapper.updatePayMoney(map);
				} else {
					Map<String, Object> map = new HashMap<String, Object>();
					map.put("userId", "admin");
					map.put("accountName", payOrder.getFundsAccount());
					map.put("money", payOrder.getMoney());
					accountsMapper.updatePayMoney(map);
				}
			}
		}

		return this.payOrderMapper.updatePayInfo(status, payId, platformOrder,
				platformOrderStatus);
	}

	private double calRate(Double payRate, Double money) {
		return new BigDecimal(String.valueOf(money))
				.multiply(new BigDecimal(String.valueOf(payRate)))
				.setScale(2, RoundingMode.UP).doubleValue();
	}

	private double calRate(MerchantRate merchantRate, PayOrder payOrder) {
		if (PayConstans.PAY_TYPE_ALIPAY.equals(payOrder.getType())) {
			return new BigDecimal(payOrder.getMoney()
					* merchantRate.getAlipayRate())
					.setScale(2, RoundingMode.UP).doubleValue();
		}
		if (PayConstans.PAY_TYPE_WEIXIN.equals(payOrder.getType())) {
			return new BigDecimal(payOrder.getMoney()
					* merchantRate.getWeixinRate())
					.setScale(2, RoundingMode.UP).doubleValue();
		}
		if (PayConstans.PAY_TYPE_QQ.equals(payOrder.getType())) {
			return new BigDecimal(payOrder.getMoney()
					* merchantRate.getQqRate()).setScale(2, RoundingMode.UP)
					.doubleValue();
		}
		return 0;
	}

	private double getRate(MerchantRate merchantRate, PayOrder payOrder) {
		if (PayConstans.PAY_TYPE_ALIPAY.equals(payOrder.getType())) {
			return merchantRate.getAlipayRate();
		}
		if (PayConstans.PAY_TYPE_WEIXIN.equals(payOrder.getType())) {
			return merchantRate.getWeixinRate();
		}
		if (PayConstans.PAY_TYPE_QQ.equals(payOrder.getType())) {
			return merchantRate.getQqRate();
		}
		return 0;
	}

	/**
	 * 三次通知第三方平台
	 * 
	 * @param status
	 * @param payOrder
	 * @param payUser
	 * @return
	 */
	private boolean notifyThirdParty(String status, PayOrder payOrder,
			PayUser payUser) {
		if (PayConstans.PAY_STATUS_SUCCESS.equals(status)
				&& StringUtils.isNotEmpty(payUser.getNotifyAddress())) {
			int count = 0;
			boolean notifyResult = false;
			while (count < 3
					&& (notifyResult = !this.notifyMerchant(payUser, payOrder))) {
				try {
					Thread.sleep(1000);
					count++;
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			return notifyResult;
		}
		return false;
	}

	private boolean notifyMerchant(PayUser payUser, PayOrder payOrder) {

		MultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<>();
		requestEntity.add("money", payOrder.getMoney() + "");
		requestEntity.add("remark", payOrder.getRemark());
		requestEntity.add("authToken", payOrder.getAuthToken());
		requestEntity.add("thirdPartyOrderId", payOrder.getThirdPartyOrderId());

		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
		HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<MultiValueMap<String, String>>(
				requestEntity, headers);

		try {
			ResponseEntity<String> responseEntity = restTemplate.exchange(
					payUser.getNotifyAddress(), HttpMethod.POST, httpEntity,
					String.class);
			if (responseEntity.getStatusCode().is2xxSuccessful()) {
				String responseText = responseEntity.getBody();
				return StringUtils.isNotEmpty(responseText)
						&& responseText.toLowerCase().equals("success");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	@Override
	public MerchantOrderQuery getMerchantOrderQuery(MerchantOrderQuery query) {
		PayOrder payOrder = this.payOrderMapper.selectOrderByUserIdAndMark(
				query.getUserId(), query.getRemark());

		if (null != payOrder) {
			query.setType(payOrder.getType());
			query.setMoney(payOrder.getMoney());
			query.setStatus(payOrder.getStatus());
			return query;
		}
		return null;
	}

	@Override
	public MerchantOrderQuery getThirdPartyOrderQuery(MerchantOrderQuery query) {
		PayOrder payOrder = this.payOrderMapper
				.selectOrderByUserIdAndThirdPartyOrderId(query.getUserId(),
						query.getThirdPartyOrderId());
		Date nowTtime = new Date();
		if (null != payOrder) {
			if (("1".equals(payOrder.getStatus()))
					&& ((payOrder.getPayTime().getTime() + 300 * 1000) < nowTtime
							.getTime())) {
				payOrder.setStatus("6");
			}
			query.setType(payOrder.getType());
			query.setMoney(payOrder.getMoney());
			query.setStatus(payOrder.getStatus());
			query.setFundsAccount(payOrder.getFundsAccount());
			query.setFundsAccountName(payOrder.getFundsAccountName());
			query.setQrcode(payOrder.getQrcode());
			return query;
		}
		return null;
	}

	@Override
	public PayAccounts getAccounts(String userId, String payType, double money,
			User user) {

		PayAccounts payAccounts = new PayAccounts();
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("userId", userId);
		map.put("passType", payType);

		if (user.getPackageId() != 2) {
			List<Accounts> accountsList = accountsMapper.findAccountsList(map);
			if (accountsList.size() > 1) {
				Collections.shuffle(accountsList);
			}
			for (Accounts accounts : accountsList) {
				if (accounts.getPayLimit() >= (new BigDecimal(
						String.valueOf(accounts.getCurrentPay()))
						.add(new BigDecimal(String.valueOf(money)))
						.doubleValue())) {
					BeanUtils.copyProperties(accounts, payAccounts);
					payAccounts.setPayAccountType(0);
					return payAccounts;
				}
			}
		} else {
			Config config = configMapper.findByKey("alipayswitch");
			map.put("userId", "admin");
			if ("1".equals(config.getValue())) {
				List<Accounts> accountsList = accountsMapper
						.findAccountsList(map);
				if (accountsList.size() > 1) {
					Collections.shuffle(accountsList);
				}
				for (Accounts accounts : accountsList) {
					if (accounts.getPayLimit() >= (new BigDecimal(
							String.valueOf(accounts.getCurrentPay()))
							.add(new BigDecimal(String.valueOf(money)))
							.doubleValue())) {
						BeanUtils.copyProperties(accounts, payAccounts);
						payAccounts.setPayAccountType(0);
						return payAccounts;
					}
				}
			}

			List<IntraAccounts> intraAccountsList = intraAccountsMapper
					.findAllAccountsList(map);
			if (intraAccountsList.size() > 1) {
				Collections.shuffle(intraAccountsList);
			}
			for (IntraAccounts intraAccounts : intraAccountsList) {
				if (intraAccounts.getPayLimit() >= (new BigDecimal(
						String.valueOf(intraAccounts.getCurrentPay()))
						.add(new BigDecimal(String.valueOf(money)))
						.doubleValue())) {
					BeanUtils.copyProperties(intraAccounts, payAccounts);
					payAccounts.setPayAccountType(1);
					return payAccounts;
				}
			}
		}
		return null;
	}

	public Accounts getAccounts(double money) {

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("userId", "admin");
		map.put("passType", "alipay");

		List<Accounts> accountsList = accountsMapper.findAccountsList(map);
		if (accountsList.size() > 1) {
			Collections.shuffle(accountsList);
		}
		for (Accounts accounts : accountsList) {
			if (accounts.getPayLimit() >= (new BigDecimal(
					String.valueOf(accounts.getCurrentPay()))
					.add(new BigDecimal(String.valueOf(money))).doubleValue())) {
				return accounts;
			}
		}
		return null;
	}

	public RechargeAccounts getRechargeAccounts(String payType, double money) {

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("passType", payType);

		List<RechargeAccounts> rechargeAccountsList = rechargeAccountsMapper
				.findAllAccountsList(map);
		if (rechargeAccountsList.size() > 1) {
			Collections.shuffle(rechargeAccountsList);
		}
		for (RechargeAccounts rechargeAccounts : rechargeAccountsList) {
			if (rechargeAccounts.getPayLimit() >= (new BigDecimal(
					String.valueOf(rechargeAccounts.getCurrentPay()))
					.add(new BigDecimal(String.valueOf(money))).doubleValue())) {
				return rechargeAccounts;
			}
		}
		return null;
	}

	@Override
	public boolean checkMoney(Double money) {

		Config config = config = configMapper.findByKey("paylimit");
		if (config != null) {
			if (money > Double.valueOf(config.getValue())) {
				return false;
			}
		}
		config = configMapper.findByKey("payminimum");
		if (config != null) {
			if (money < Double.valueOf(config.getValue())) {
				return false;
			}
		}

		return true;
	}

	private Seller findSeller(List<Seller> sellerList, String accountName) {

		if (CollectionUtils.isEmpty(sellerList)) {
			return null;
		}

		for (Seller seller : sellerList) {
			if (accountName.equals(seller.getAccountName())) {
				return seller;
			}
		}
		return null;
	}

	@Override
	public void setAccountsPayMoneyZero() {
		accountsMapper.setPayMoneyZero();
	}

	@Override
	public WebSocketResponse recharge(UserPay userPay) {

		userPay.setTime(System.currentTimeMillis());
		System.out.println("服务端发起支付:" + JSON.toJSONString(userPay));

		WebSocketResponse response = new WebSocketResponse();
		response.setCode(ProtocoConsts.SUCCESS);
		response.setData(userPay);

		PayOrder payorder = new PayOrder(userPay);
		payorder.setPayId(userPay.getPayId());
		payorder.setThirdPartyOrderId(userPay.getRemark());
		payorder.setStatus(PayConstans.PAY_STATUS_REQUEST);
		payorder.setUserId("admin");
		payorder.setType(userPay.getType());
		payorder.setMoney(userPay.getMoney());
		payorder.setRemark(userPay.getRemark());
		payorder.setPayTime(new Date());
		payorder.setFundsAccount(userPay.getFundsAccount());
		payorder.setPayType(userPay.getPayType());
		payorder.setRechargeAccount(userPay.getUserId());
		payorder.setFundsAccountName(userPay.getFundsAccountName());
		payOrderMapper.insert(payorder);

		return response;
	}

	public static void main(String agrs[]) throws AlipayApiException {

		final String APPID = "2018122662653934";
		String PID = "2088431033116893";
		// String RSA2_PRIVATE =
		// "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCv/1BM9OxbJsx+lP9JnHAGkxhKI7j7UaN10kxwAkxobQgxZl68YwTE0LIRdk08gnSxFWnMWpU9hvWAJZy+BgRaN8qCJk1B0fXaOnw1zl3USvDDaHUg0lmC8NbSe3dGOzN+WWfbGEmbJvuzJorbi47F4fODuiuX2KiFmeHrZ1VqxTr1MSZyZUooOlrcBDlrUd9w/iC70tMM4lYD3bC/Xw1wlWQERpYzS0bjVnrzG2y0WRV17hLr9ycbW2DSqCu6C8OuXz4FUJYiQO83EUidlbE9HAa+teFXwFtVPYwa5b0kFu6VukikjUvSlFGtEWabu8v1nKIqQCrA3PIPA+CYoUvLAgMBAAECggEBAJpR+55PEERow9ymVya7hjstlZnEsvmjPvobuSxpx4e1Ov7d7WmwRUkyWUEYg2bwWNPBm/A06TF2+iMwV70DV6On0ejHHuz85l9A8xLW7c0tHOmq2TE7YIOBHEyZOB+b324FhRxGspvZ1c/jltQlDb6Tfkvd3UWbE0F6ie84v1wLOnoMRxbZqRxFguLHEtrPgtYOzy1qfSo/Mnllh7gCtd3PJi4vvuwfQNrwgH/HvRCckB/1CoQ4eqRQlzYuL90Smwmm37ZNx7GFAxnU1WVn07L9JJ+uLKSzpI+o6OLbaKTo9ADqQ/Uvgp8d62RdeoBo1qhV+UkERnSat5Jx/Nq1SPECgYEA16YZ/QnQYmYnTN2xV22Nsbj841ZWJTrukUBTZhEeu+1EbxEkdxZ6MEQHey3pgMovawF0Gd8WGnU3n3tVEFuSanZ4yb1DqzzAuW0dgXkPMGvc6Pe3IjzkvX+bDAxgobbM8Hfmx5Pw6DMypdHwq6sUc2xvT7BBVMhRlVycZnrX2LkCgYEA0O3YixOtVyzS90pB6UsY2GMpwqr0G4AmZk3i+8hAo8QBbH6+ylvkh5M3aJVlwTw+5QDTrugPOrfGiM9EJa92NRMhRmCkyN1BklgiejpfBOIeLt33I/yBZkRyrLIaHu510fgcJEI6MgcrRl9WCJWyYDcdgAcdZOyaweSyhvKhvqMCgYBD062W5fBSErlHtu7hhcasYHfB9VTRDvEcZHQWxUm6aA0/NdAXWM2DwtHrj2xDItS5PlLLFFy6Y6XkFoGRzIuHys2A/nN7N3eSmtxN7cq2OybXa5qBPU/gvnMA3h/CnWFmPQAsQ77g+cFzYE3nYL7k8vUrxk82IG9woBldLkQXmQKBgGG4bYkXSgM1LvOFIvD4NAW50+V+SjC2rr84/MqhLkKqwbO6UIiblHcpD0h2YCKSiCRaT6hGWCExpcWFlC1ANTy71ttxBoIAotPNL0sWFC1XiaCIJzkIuIlZyH0nzHndNPRhZOA8rbWKjt4aZ0YaplTEUqL4MPJsjDHWQv5FbAubAoGBAJBaySakcv3BZQJdnKLeE2hmIACcdWeGJiVV+y6jo0vJ+0vMJYEo3Hw95LJRfO11RUsw1r5+e0kNPsRG1Qu+K1jdJQpJirQkD9/jL1xY1V/MYubytpZ6zs4sNGBYXwa3iQBm/zZIhZbSA/CCwy26fT3TM5yGOp7/pM3TzeQ8baPa";
		// String ALIPAY_PUBLIC_KEY =
		// "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjEZZlTDwWRuyZwYTJZjWiAi3k/z5NFMJpN53A9k5B7Ng/4R5y7l+a57qlhSr1gsWsd9JureIfS4WYLSHbPbREwPfAH6QIets1CO4uH9yMihF89JMebY74fm4e8kVBkGQNF3ZHXQqluIH2PoPDNPUXttT6eKfs9COwd3cjjXGrughYDSKNRTYbPl5CFWjI7+ipYBLkMzahQNOdVfGN2xf11XCByoL+5Z6oQIQzPlOJJdBuVK9BKgAmbXmBIDsPiBOWzP9U1DSvUhuCN8ZKmF7BSCg/qFMOT6x4r5YWU+0jdbVpPJa5QidA72vgjzMbEkAg8kNUcjwpT69GMQlsCIN8wIDAQAB";

		String privateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCa5s947/zFhlvk0WdlbkabIi9Hx7OrWe4dMk+BchCj3OWg9s7sENPkRcxt4XhgpAVYKTDREP5u6wndBFJFZvFq/WPjQtTNQeeKq/YQW35J0rYWhRIFhgkJa8zsgDA1N+Un9NuAGh8bDE1RM4WM8Ut5HnvSz+422qVhwB0+iEvnk+XJ6TfjeoD7gfS1pV0SbS4p19Mjeef8glmUeK6MCvr91qMhVowXrDhSDqBecBtyrA/dLjeHEkDMidMkpGy1BuH/UkYeIa8l76B+G1IAyUfv3DDzoWwdWM7vQGC2KL+OOPfzvSEeB/R1KqO6YTG/aul0jiCInle2cXA31RNu1rF3AgMBAAECggEAKm+E8xq74tkWH6+GZfE6ApHw5fc9r3mpk/IOeeXnzRxdBCXZNi69/dFpWcjlE4SbujU+nGfNbFGTmCrw5vZ2uNrGHKJYbgraBdFqTbzi8hJ5s92svDqmCyCvOTM9AbdYXgPkhkmhr+VE4TP+KEiKZpoFThGMrxZjLE5XNKReNwiL7qiH8Fr2KEqWYwP/RqhSw62ixZgBApj0GtHd502hKabcDPBFa3MJ5RYSrSO1SUOPRl3Nom4m/uxhvcXXUffDHHauJSRTFIMRrbKFhfVb6Eerl/FXwqQJoQF5ca62Xu1ATQnj/5Lr/Jx1OqiL8OjXaxN5pVWvsRg1nOB75WjfsQKBgQD1hlltau5RcKIiRjOXhhUlDu7SQS+2gUvZhBwAd4AIwO3U7UzPVg0iNsppizMYCJNhKnSz0qGqPYEOx2/6R+7nhiBuDmSm5MJZm9q0fj/wLdLGofx+mqDofGmc5rRvzrcUALVgqs590U26IoQ21DEaDOQiY1Ogutg/ylsqipV00wKBgQChgqn2Fvoc2IQvqgN2Zz+iCyJnA/UsrotqMcGXrW5HmbujZtKjAllmPQgLxnUD6fS+LyFf4j3dLkiqNiRgSrcBDsViSZfmR05TZFh3hJsN0VP9arKXgKsBqvH+FVHOByX2KvM0WiUF1QyJ5tSzmtMHcVGUKevSsMU1t2RIVzJ6TQKBgQC/GQeHu1+scY8wQBWtzQWuJ1ZIvcXmNfKUZVfqIRi9N3SlcuGCywZD6ANZbKejACG90e6te7aqq15E44PLeKuA9otNPdSndYuzdTQfodggF3pjcfb1j2LIMPV+0q4EDA/A+OAzUh6QHRVzV6QyjKt/DCOQhGC1zFe+JsEYdm7nUwKBgQCNNqaOITbcA79HwXm3i7zKXLveoEo8n/wLhKeEi8HRXqv9yYg/uG0cBB7F1OY43tT7eE/Q+womGjK0iBQ0EP+DMDwKnNfwIsZsCV+EWHANm8m42BKAfqKGGcXt5wwYfI2Hd7QfQPX/7HBDHo044BTE/CJczm5/T8mOFuPakEr1PQKBgGpgrJqBf+FlTXlEADRQtsG2rVaxuE8BpjVGzfjOM51EJ4nEx6cpuqwaSbg0TKDJVl4o6Jp3rBaOS54U+cf/cfIlGoIgufY78MkMQAyZRAcdLfsy3S1CPERdr4InZzXnQRpO/49F3vIERDkzVk3afeLy+p1lwIXwTWY9Iq3Qfwxu";
		String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiCBHR+WnVyx6jfai7DOalCOoE6sheHklZ+JfNPWAEuKr2LRt3gvzVx1kwNTLQe0YssgdmtuWPOfVfJ/tE55MX3FXj5a71wQ3OTja8LwZ0Xu91FxE7SN4+NcL+GOUry9cpmoxmcrmRRRIBTXcH6dXp7q6j1bYIBMZtk5uiMWS4Q7fAOvC/56GeyPvm/56kUibS8SFNUP1rtu6eQ/PCrmgXaOcvnla1r2X6F/9kqySXfhXmQ3SJQHZzyAyIIkaW8OzSVT66wn+ATQppHTu2BH7JE9C1sDIW170CF7jDdzBKf8bJnpMt9V8MS232ep565LbZStyWF3beRS4QAgb2xwl9QIDAQAB";

		// Date now = new Date();
		// SimpleDateFormat dateFormat = new
		// SimpleDateFormat("yyyyMMddHHmmss");// 可以方便地修改日期格式
		// String hehe = dateFormat.format(now);
		//
		// String order_no = hehe + "scancodealipay"; // 77777777
		// String body = "";
		//
		// String total_fee = "0.01"; // 真实金钱
		//
		// AlipayClient alipayClient = new DefaultAlipayClient(
		// "https://openapi.alipay.com/gateway.do", APPID, privateKey,
		// "json", "UTF-8", alipayPublicKey, "RSA2"); // 获得初始化的AlipayClient
		// AlipayTradePrecreateRequest request = new
		// AlipayTradePrecreateRequest();// 创建API对应的request类
		// request.setBizContent("{" + "    \"out_trade_no\":\"" + order_no
		// + "\"," + "    \"total_amount\":\"" + total_fee + "\","
		// + "    \"body\":\"" + body + "\","
		// + "    \"subject\":\"扫码支付\","
		// + "    \"timeout_express\":\"90m\"}");// 设置业务参数
		// // request.setNotifyUrl("你的外网异步通知地址");
		// AlipayTradePrecreateResponse response =
		// alipayClient.execute(request);// 通过alipayClient调用API，获得对应的response类
		// System.err.print(response.getBody());
		// // 根据response中的结果继续业务逻辑处理
		// if (response.getMsg().equals("Success")) {
		// String qrcode = response.getQrCode();
		// System.out.println(qrcode);
		// // return qrcode;
		// }
		AlipayClient alipayClient = new DefaultAlipayClient(
				"https://openapi.alipay.com/gateway.do", APPID, privateKey,
				"json", "GBK", alipayPublicKey, "RSA2");
		AlipayTradeOrderSettleRequest request = new AlipayTradeOrderSettleRequest();
		request.setBizContent("{" + "\"out_request_no\":\"20142250727001\","
				+ "\"trade_no\":\"2019010422001488310574743309\","
				+ "      \"royalty_parameters\":[{" + "        \"trans_out\":"
				+ PID + "," + "\"trans_out_type\":\"userId\","
				+ "\"trans_in_type\":\"userId\","
				+ "\"trans_in\":\"2088332506636390\"," + "\"amount\":1.00,"
				+ "\"amount_percentage\":100,"
				+ "\"desc\":\"分账给2088132858684322\"" + "        }],"
				+ "\"operator_id\":\"A0001\"" + "  }");
		AlipayTradeOrderSettleResponse response = alipayClient.execute(request);
		if (response.isSuccess()) {
			System.out.println("调用成功");
		} else {
			System.out.println("调用失败");
		}
	}

	@Override
	public int updatePayInfo(String status, String payId, String platformOrder,
			String platformOrderStatus, IntraAccounts intraAccounts) {

		PayOrder payOrder = this.payOrderMapper.selectById(payId);
		if (payOrder == null) {
			return 0;
		}

		User user = userMapper.findByUsername(payOrder.getUserId());
		if (user == null) {
			return 0;
		}

		if (!"1".equals(payOrder.getStatus())) {
			return 0;
		}

		// 对商户余额扣款与添加扣款明细
		if (PayConstans.PAY_STATUS_SUCCESS.equals(status)) {
			// 费率
			CustomRate customRate = customRateMapper.findByUserId(user
					.getUsername());
			Double payRate = 0.0;
			if (customRate != null) {
				payRate = customRate.getRate();
			} else {
				Package packageEntity = packageMapper.findPackageById(user
						.getPackageId());
				payRate = packageEntity.getRate();
			}

			double deductionMoney = this.calRate(payRate, payOrder.getMoney());
			MerchantDeductionDetail merchantDeductionDetail = new MerchantDeductionDetail(
					payOrder, deductionMoney);
			merchantDeductionDetail.setRate(user.getPayRate());
			merchantDeductionDetailMapper.insert(merchantDeductionDetail);
			userMapper.updateBalance(user.getUsername(), -deductionMoney);

			userMapper.updateAmount(user.getUsername(), payOrder.getMoney());

			// if (user.getPackageId() != 2) {
			// Map<String, Object> map = new HashMap<String, Object>();
			// map.put("userId", payOrder.getUserId());
			// map.put("accountName", payOrder.getFundsAccount());
			// map.put("money", payOrder.getMoney());
			// accountsMapper.updatePayMoney(map);
			// } else {
			// Map<String, Object> map = new HashMap<String, Object>();
			// map.put("userId", "admin");
			// map.put("accountName", payOrder.getFundsAccount());
			// map.put("money", payOrder.getMoney());
			// accountsMapper.updatePayMoney(map);
			// }
		}

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("money", payOrder.getMoney());
		map.put("payId", payId);
		map.put("tradeNo", platformOrder);
		map.put("appid", intraAccounts.getAppid());
		transferMapper.addTransfer(map);

//		Accounts accounts = getAccounts(payOrder.getMoney());
//		if (accounts != null) {
//			try {
//				transferMoney(intraAccounts, accounts, payOrder.getMoney(),
//						payOrder.getPayId(), platformOrder);
//			} catch (AlipayApiException e) {
//				e.printStackTrace();
//			}
//		}
		return this.payOrderMapper.updatePayInfo(status, payId, platformOrder,
				platformOrderStatus);
	}

	void transferMoney(IntraAccounts intraAccounts, Accounts accounts,
			Double money, String payId, String platformOrder)
			throws AlipayApiException {
		AlipayClient alipayClient = new DefaultAlipayClient(
				"https://openapi.alipay.com/gateway.do",
				intraAccounts.getAppid(), intraAccounts.getPrivateKey(),
				"json", "GBK", intraAccounts.getPublicKey(), "RSA2");
		AlipayTradeOrderSettleRequest request = new AlipayTradeOrderSettleRequest();
		request.setBizContent("{" + "\"out_request_no\":\"" + payId + "\","
				+ "\"trade_no\":\"" + platformOrder + "\","
				+ "      \"royalty_parameters\":[{"
				+ "        \"trans_out\":\"" + intraAccounts.getPid() + "\","
				+ "\"trans_out_type\":\"userId\","
				+ "\"trans_in_type\":\"userId\"," + "\"trans_in\":\""
				+ accounts.getAccountName() + "\"," + "\"amount\":"
				+ String.valueOf(money) + "," + "\"amount_percentage\":100,"
				+ "\"desc\":\"分账\"" + "        }],"
				+ "\"operator_id\":\"A0001\"" + "  }");
		AlipayTradeOrderSettleResponse response = alipayClient.execute(request);
		if (response.isSuccess()) {
			System.out.println("调用成功");
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("userId", "admin");
			map.put("accountName", accounts.getAccountName());
			map.put("money", money);
			accountsMapper.updatePayMoney(map);

			map.clear();
			map.put("accountName", accounts.getAccountName());
			map.put("money", money);
			map.put("payId", payId);
			transferMapper.addTransfer(map);
		} else {
			System.out.println("调用失败");
		}
	}
}
